package com.example.demo.test;

import com.example.demo.LockData;
import com.example.demo.LockTaskCallback;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Lock;

import static com.example.demo.test.LockManager.LOCKS;


public class DefaultTaskCallback implements LockTaskCallback {


    private final List<Lock> currentLocks;

    private final Object lock = new Object();

    public DefaultTaskCallback() {
        this.currentLocks = new ArrayList<>(16);
    }


    public synchronized void addLock(Lock lock) {
        currentLocks.add(lock);
    }

    public synchronized void onComplete(Lock lock) {
        currentLocks.remove(lock);
        lock.unlock();
    }


    @Override
    public void run() {

        while (true) {
            Iterator<Map.Entry<Lock, LockData>> iterator = LOCKS.entrySet().iterator();
            while (iterator.hasNext()) {
                Map.Entry<Lock, LockData> entry = iterator.next();
                synchronized (lock) {
                    if (currentLocks.contains(entry.getKey())) {
                        if (entry.getValue().isFinished()) {
                            iterator.remove();
                        }
                        Long startTime = entry.getValue().getStartTime();
                        long diff = System.currentTimeMillis() - startTime;
                        Long timeOut = entry.getValue().getTimeOut();
                        if (diff > (timeOut * 1000 * 0.9 * (1 + entry.getValue().getCount()))) {
                            int count = entry.getValue().getCount();
                            count++;
                            entry.getValue().setCount(count);
                            System.err.println(entry.getKey() + "第" + count + "次延时");
                            try {
                                entry.getKey().tryLock(timeOut, TimeUnit.SECONDS);
                            } catch (InterruptedException e) {
                                e.printStackTrace();
                            }
                        }
                    }
                }

            }
        }

    }
}